# -*- coding: utf-8 -*-

import numpy as np
import single


def IsInTri(p, pos):
    mat = np.zeros((3, 3))
    mat[:, 2] = 1.0
    for i in range(-1, 2):
        mat[0, :2] = p[i]
        mat[1, :2] = p[i + 1]
        mat[2, :2] = pos
        if np.linalg.det(mat) < 0:
            return False
    return True


def GetTarget(here, there, subject_point=None, rmax=single.RMAX, rmin=single.RMIN, in_points=None):
    target, subject_point = single.GetTargetSubjectPoint(here, there, subject_point, rmax)
    if subject_point is None:
        subject_point = np.zeros((0, 2))
    if in_points is None:
        in_points = np.zeros((0, 2))
    in_points = in_points.copy()
    subject_point = subject_point.copy()
    subject_point[:] -= here
    in_points[:] -= here
    in_points = np.vstack((in_points, [[0, 0]]))
    target -= here
    w = np.linalg.norm(in_points, axis=1).max() + 0.01
    if w > rmin:
        return None, None
    if w < rmin:
        w = rmin
    w *= 2
    h = 2*rmax
    seg = 60
    a0 = np.arctan2(target[1], target[0])
    for i in range(seg + 1):
        for j in [-1, 1]:
            a = j * np.pi * i / seg + a0
            p1 = np.array([np.sin(a), -np.cos(a)]) * w / 2
            p2 = np.array([-np.sin(a), np.cos(a)]) * w / 2
            p3 = np.array([np.cos(a), np.sin(a)]) * (h - w / 2)
            p4 = p3 + p1
            p5 = p3 + p2
            p6 = np.array([np.cos(a), np.sin(a)]) * (h - w)
            p7 = np.array([np.cos(a), np.sin(a)]) * (- w / 2)
            p1 += p7
            p2 += p7
            # p1, p4, p5, p2
            tri1 = [p1, p4, p5]
            tri2 = [p1, p5, p2]
            bOut = True
            for k in range(subject_point.shape[0]):
                if IsInTri(tri1, subject_point[k]):
                    bOut = False
                    break
                if IsInTri(tri2, subject_point[k]):
                    bOut = False
                    break
            if bOut:
                split_d = 0.05
                plst = [p1, p4, p5, p2]
                sample = np.zeros((0, 2))
                for k in range(-1, len(plst)-1):
                    p1 = plst[k]
                    p2 = plst[k+1]
                    d = np.linalg.norm(p1 - p2)
                    n = int(d/split_d) + 1
                    ps = np.zeros((n, 2))
                    for i in range(2):
                        ps[:, i] = np.linspace(p1[i], p2[i], n)
                    sample = np.vstack((sample, ps))
                p6 += here
                sample += here
                return p6, (sample[:, 0], sample[:, 1])
    return None, None